package com.qijian.tool.utils;

import cn.hutool.core.date.DatePattern;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.qijian.common.utils.DateUtils;
import com.qijian.common.utils.StringUtils;
import com.qijian.tool.domain.Msg;
import com.qijian.tool.domain.WxMsg;
import me.chanjar.weixin.cp.api.WxCpMessageService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.article.NewArticle;
import me.chanjar.weixin.cp.bean.message.WxCpMessage;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.net.URLEncoder;
import java.util.List;
import java.util.stream.Collectors;

@Component("wxUtil")
public class QyWxUtil {

    private static final Logger log = LoggerFactory.getLogger(QyWxUtil.class);

    @Autowired
    private WxCpService wxCpService;

    @Value("${wechat.oauthUrl}")
    private String wxCpConfig;


    @Value("${wechat.flowableRedirectPrefix}")
    private String flowableRedirectPrefix;

    @Value("${wechat.signRedirectPrefix}")
    private String signRedirectPrefix;

    /**
     * 将流程消息发送给微信
     *
     * @param msg
     */
    public String sendFlowMsg2Wx(Msg msg) {
        // 校验微信用户id
        String res = validateWxUserId(msg);
        if (res != null) return res;

        WxMsg wxMsg = new WxMsg();
        BeanUtils.copyProperties(wxMsg, msg);

        return buildAndSendFlowMsg2Wx(wxMsg, msg.getWxUserId());
    }


    /**
     * 将提醒消息发送给微信
     *
     * @param msg
     */
    public String sendMsg2Wx(Msg msg) {
        // 校验微信用户idr
        String res = validateWxUserId(msg);
        if (res != null) return res;

        WxMsg wxMsg = new WxMsg();
        BeanUtils.copyProperties(wxMsg, msg);

        return buildAndSendMsg2Wx(wxMsg, msg.getWxUserId());
    }

    private static String validateWxUserId(Msg msg) {
        if (null == msg.getWxUserId()) {
            String res = "用户:[" + msg.getReceiverName() + "] 系统内未配置企业微信账号!";
            log.error(res);
            return res;
        }
        return null;
    }


    /**
     * 将提醒消息批量的发送给 wxUserId
     *
     * @param msgs
     */
    public String sendMsg2WxBatch(List<Msg> msgs) {
        // 转换成微信消息
        WxMsg wxMsg = buildWxMsg(msgs);
        if (wxMsg == null) return "转换成微信消息失败";
        String res = validateWxUserIds(msgs);
        // 校验微信用户信息
        if (res != null) return res;

        String wxUsers = msgs.stream().map(Msg::getWxUserId).collect(Collectors.joining("|"));

        return buildAndSendMsg2Wx(wxMsg, wxUsers);
    }

    /**
     * 将流程消息批量的发送给 wxUserId
     *
     * @param msgs
     */
    public String sendFlowMsg2WxBatch(List<Msg> msgs) {
        // 转换成微信消息
        WxMsg wxMsg = buildWxMsg(msgs);
        if (wxMsg == null) return "转换成微信消息失败";

        // 校验微信用户信息
        String res = validateWxUserIds(msgs);
        if (res != null) return res;

        String wxUsers = msgs.stream().map(Msg::getWxUserId).collect(Collectors.joining("|"));
        // 构建并发送
        return buildAndSendFlowMsg2Wx(wxMsg, wxUsers);
    }

    @Nullable
    private static WxMsg buildWxMsg(List<Msg> msgs) {
        if (CollectionUtils.isEmpty(msgs)) {
            return null;
        }

        // 获取微信消息对象
        WxMsg wxMsg = new WxMsg();
        BeanUtils.copyProperties(msgs.get(0), wxMsg);
        return wxMsg;
    }

    private static String validateWxUserIds(List<Msg> msgs) {
        String res = null;
        // 是否存在无法识别的微信对象
        String unSupportUsers = msgs.stream().filter(e -> StringUtils.isEmpty(e.getWxUserId())).map(Msg::getReceiverName).collect(Collectors.joining("|"));

        if (StringUtils.isNotEmpty(unSupportUsers)) {
            res = "用户:[" + unSupportUsers + "] 系统内未配置企业微信账号!";
            log.info(res);
            return res;
        }
        return res;
    }


    /**
     * @param wxMsg   微信消息
     * @param wxUsers 微信接受者
     */
    private String buildAndSendFlowMsg2Wx(WxMsg wxMsg, String wxUsers) {
        String res;
        try {
            String targetRoute = "?flowType=" + wxMsg.getSourceType() + "&id=" + wxMsg.getSourceId() + "&taskId=" + wxMsg.getTaskId() + "&processInstanceId=" + wxMsg.getProcessInstanceId();
            targetRoute = flowableRedirectPrefix + URLEncoder.encode(targetRoute, "UTF-8");
            if (wxMsg.getSourceType().startsWith("sign_")) {
                targetRoute = "?signType=" + wxMsg.getSourceType() + "&flowId=" + wxMsg.getSourceId()+  "&id=" + wxMsg.getSourceId() + "&taskId=" + wxMsg.getTaskId() + "&processInstanceId=" + wxMsg.getProcessInstanceId();
                targetRoute = signRedirectPrefix + URLEncoder.encode(targetRoute, "UTF-8");
            }
            String targetUrl = String.format(wxCpConfig, targetRoute);

            log.info("####################################################################################\n" + targetUrl + "\n####################################################################################");
            WxCpMessageService messageService = wxCpService.getMessageService();

            //卡片消息
            WxCpMessage message = WxCpMessage.NEWS()
                    .toUser(wxUsers)
                    .addArticle(NewArticle.builder()
                            .title(wxMsg.getTitle())
                            .description("创建人:" + wxMsg.getCreateByName() + "\n创建时间:" + DateUtils.format(wxMsg.getOriginCreateDateTime(), DatePattern.NORM_DATETIME_PATTERN))
                            .url(targetUrl)
                            .build()).build();
            res = messageService.send(message).toString();

        } catch (Exception e) {
            res = e.getMessage();
            log.error(res);
            return res;
        }
        return res;
    }


    /**
     * @param msg     微信消息
     * @param wxUsers 微信接受者
     */
    private String buildAndSendMsg2Wx(WxMsg msg, String wxUsers) {
        String res;
        try {
            String title = msg.getTitle();
            if (title != null && !title.contains("消息提醒:")) {
                title = "消息提醒:" + title;
            }
            WxCpMessageService messageService = wxCpService.getMessageService();
            WxCpMessage message = WxCpMessage.NEWS()
                    .toUser(wxUsers)
                    .addArticle(NewArticle.builder()
                            .title(title)
                            .description("<div class=\"highlight\">请进入系统查看详情!</div>\n推送时间:" + DateUtils.getCurrentStrDate("YYYY-MM-dd HH:mm:ss"))
                            .build()).build();
            res = messageService.send(message).toString();

        } catch (Exception e) {
            res = e.getMessage();
            log.error(res);
            return res;
        }
        return res;
    }

}
